package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.UserDto;
import com.zzyl.entity.User;
import com.zzyl.entity.UserRole;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.UserMapper;
import com.zzyl.mapper.UserRoleMapper;
import com.zzyl.service.UserService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    @Cacheable(cacheNames = "user:page",key = ("#userDto.hashCode()+#pageNum+#pageSize"))
    public PageResponse<UserVo> selectByPage(UserDto userDto, Integer pageNum, Integer pageSize) {
        User user = BeanUtil.toBean(userDto, User.class);
        String deptNo = NoProcessing.processString(user.getDeptNo());
        user.setDeptNo(deptNo);
        PageHelper.startPage(pageNum, pageSize);
        Page<UserVo> page = userMapper.selectByPage(user);
        PageResponse<UserVo> of = PageResponse.of(page, UserVo.class);
        return of;
    }

    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(cacheNames = "user:page",allEntries = true),
            @CacheEvict(cacheNames = "user:list",allEntries = true)
    })
    public Boolean addUser(UserDto userDto) {
        Integer row = null;
        User user = BeanUtil.toBean(userDto, User.class);
        try {
            user.setIsDelete(0);
            user.setIsLeader(0);
            user.setNickName(userDto.getRealName());
            user.setUsername(userDto.getEmail());
            String password = BCrypt.hashpw("888itcast.CN764%...", BCrypt.gensalt());
            user.setPassword(password);
            row = userMapper.insertUser(user);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.DATA_IS_EXIST_ERROR);
        }


        List<UserRole> list = userDto.getRoleVoIds().stream().map(roleVoId -> {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(Long.valueOf(roleVoId));
            return userRole;
        }).collect(Collectors.toList());

        userRoleMapper.insertUserRoles(list);

        if (row > 0) {
            return true;
        }
        return false;
    }

    @Override
    @Cacheable(cacheNames = "user:list",key = ("#userDto.hashCode()"))
    public List<UserVo> selectUserList(UserDto userDto) {
        User user = BeanUtil.toBean(userDto, User.class);
        List<UserVo> list = userMapper.selectUserList(user);
        return list;
    }

    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(cacheNames = "user:page",allEntries = true),
            @CacheEvict(cacheNames = "user:list",allEntries = true)
    })
    public Boolean updateUser(UserDto userDto) {
        User user = BeanUtil.toBean(userDto, User.class);
        user.setNickName(userDto.getRealName());
        user.setUsername(userDto.getEmail());
        //更新用户数据
        Integer row = null;
        try {
            row = userMapper.updateUser(user);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.DATA_IS_EXIST_ERROR);
        }

        //删除原有角色数据
        userRoleMapper.deleteUserRoleByUserId(userDto.getId());

        //插入更新后的角色数据
        List<UserRole> list = userDto.getRoleVoIds().stream().map(roleVoId -> {
            UserRole userRole = new UserRole();
            userRole.setUserId(userDto.getId());
            userRole.setRoleId(Long.valueOf(roleVoId));
            return userRole;
        }).collect(Collectors.toList());

        userRoleMapper.insertUserRoles(list);

        return row > 0;
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = "user:page",allEntries = true),
            @CacheEvict(cacheNames = "user:list",allEntries = true)
    })
    public void updateStatus(Long id, String status) {
        User user = new User();
        user.setId(id);
        user.setDataState(status);
        userMapper.updateUser(user);
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = "user:page",allEntries = true),
            @CacheEvict(cacheNames = "user:list",allEntries = true)
    })
    public void deleteUser(String userId) {
        userMapper.deleteUser(userId);
    }

    @Override
    public Boolean resetPassword(String userId) {
        String pwd = BCrypt.hashpw("888itcast.CN764%...", BCrypt.gensalt());
        User user = new User();
        user.setPassword(pwd);
        user.setId(Long.valueOf(userId));

        Integer row = userMapper.updatePwd(user);
        return row > 0;
    }
}
